package game.map.block;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedList;

import common.Area;
import common.Coordinate;
import common.Log;
import common.Rectangle;

import game.map.MapInfo;
import game.physics.CollisionGroup_I;
import game.physics.MapCollision;
import game.physics.SimulationBody;

public class BlockMap implements CollisionGroup_I {
	public BlockMap(MapInfo mapInfo) {
		redimension(mapInfo);
	}
	private int _CellWidth;
	private int _CellHeight;
	private int _Width;
	private int _Height;
	private int _ObstacleCount;
	private boolean[][] _Cells;

	public void redimension(MapInfo mapInfo) {
		boolean[][] cells = new boolean[mapInfo.Height][mapInfo.Width];
		_ObstacleCount = 0;
		if(_Cells != null) {
			int maxY = Math.min(mapInfo.Height, _Height);
			int maxX = mapInfo.Width;
			if(maxX > _Width) {
				maxX = _Width;
			}
			for(int y = 0; y < maxY; y++) {
				for(int x = 0; x < maxX; x++) {
					if(_Cells[y][x] == true) {
						_ObstacleCount++;
					}
					cells[y][x] = _Cells[y][x];
				}
			}
		}
		
		_CellWidth = mapInfo.CellWidth;
		_CellHeight = mapInfo.CellHeight;
		_Width = mapInfo.Width;
		_Height = mapInfo.Height;
		_Cells = cells;
	}
	
	public void reset() {
		if(_Cells == null) {
			return;
		}
		for(int y = 0; y < _Height; y++) {
			for(int x = 0; x < _Width; x++) {
				_Cells[y][x] = false;
			}
		}
		_ObstacleCount = 0;
	}
	public void set(boolean isBlocking, int x, int y) {
		if(x < 0 || y < 0 || x >= _Width || y >= _Height) {
			return;
		}
		if(isBlocking == _Cells[y][x]) { // No change
			return;
		}
		if(isBlocking == true) {
			_ObstacleCount++;
		} else {
			_ObstacleCount--;
		}
		_Cells[y][x] = isBlocking;
	}

	@Override
	public LinkedList<MapCollision> collide(Rectangle collider) {
		if(collider == null) {
			return null;
		}
		int x1 = Math.max(collider.X / _CellWidth, 0);
		int y1 = Math.max(collider.Y / _CellHeight, 0);
		int x2 = Math.min(x1 + (collider.Width / _CellWidth), _Width - 1);
		int y2 = Math.min(y1 + (collider.Height / _CellHeight), _Height - 1);
		LinkedList<MapCollision> output = new LinkedList<MapCollision>();
		Rectangle rect = new Rectangle(0, 0, _CellWidth, _CellHeight);
		Coordinate coord;
		for(int y = y1; y <= y2; y++) {
			for(int x = x1; x <= x2; x++) {
				if(_Cells[y][x] == true) {
					coord = new Coordinate(x * _CellWidth, y * _CellHeight);
					rect.X = (int)coord.X;
					rect.Y = (int)coord.Y;
					output.add(new MapCollision(rect.clone()));
				}
			}
		}
		if(output.size() > 0) {
			return output;
		} else {
			return null;
		}
	}

	@Override
	public Area[] getObstacles() {
		if(_ObstacleCount == 0) {
			return null;
		}
		Area[] output = new Area[_ObstacleCount];
		Rectangle rect = new Rectangle(0, 0, _CellWidth, _CellHeight);
		Coordinate coord;
		int index = 0;
		for(int y = 0; y < _Height; y++) {
			for(int x = 0; x < _Width; x++) {
				if(_Cells[y][x] == true) {
					coord = new Coordinate(x * _CellWidth, y * _CellHeight);
					output[index++] = new Area(coord, rect.clone());
				}
			}
		}
		return output;
	}
}